﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

/* 
 * 这个脚本是用来控制敌人AI的，目前敌人的设计要点有：
 * 1.敌人具有多种形态，各种形态敌人的性格不同，敌人对玩家攻击方式不同，玩家采取攻击策略也应该不同
 * 2.玩家能够快速解决战斗，战斗时间不应过长，
 * 3.敌人是拥有生命的动物，会有各种可爱的反应
 */

 /*
  * void FixedUpdate()和void UpdateFSM()是整个脚本的主要控制流入口
  * 这个脚本主要通过不断测试不同状态下敌人与玩家之间的各种参数来决定是否进行状态的跳转（是否游戏开销很大？后期考虑一下……）
  */

public enum FSMEnemyState                                       //这个枚举是用来描述敌人的状态的
{
    Wonder,                                                     //没有遇到玩家的漫游状态
    Chase,                                                      //遇到玩家后的追逐状态
}

public class EnemyAI : MonoBehaviour {

    private Transform m_transform;                               //这里定义敌人自身的transform组件供后面使用
    private Transform m_playertransform;                         //这里定义玩家的transform组件供后面使用
    private Vector3 nextwonderposition;                          //这里定义vector3向量存储下一个漫游地点            
    private NavMeshAgent m_Navagent;                             //这里定义导航代理组件供后面使用
    public GameObject m_bullet;                                 //这里定义子弹组件供后面使用

    private Transform enmfire_Position;            //敌人发射位置
    public float shellSpeed=30f;                    //敌人子弹速度
    private float shellRange = 0.02f;//子弹偏差
    private float shoottimer=0f;                                 //这里定义辅助实现射击效果的计时器供后面使用
    public float wonderscope;                                    //这里定义漫游范围（一个圆形区域）的半径值
    public float sightscope;                                     //这里定义敌人的视野范围（一个圆形区域）的半径值
    public FSMEnemyState currentState;                           //这里定义一个枚举来表示当前玩家状态，脚本不断监测这个枚举的变化来实现敌人状态转换

	// Use this for initialization
	void Start () {
        m_transform = gameObject.GetComponent<Transform>();
        m_Navagent = gameObject.GetComponent<NavMeshAgent>();
        m_playertransform = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
        //   m_bullet = Resources.Load("Shell") as GameObject;
       // enmfire_Position = GameObject.Find("enefire_Position").transform;
        enmfire_Position = this.transform.Find("enefire_Position");//上面的方法会导致在其他AI上发射子弹
        
        currentState = FSMEnemyState.Wonder;                     //初始化敌人状态为漫游状态
        setnewwondertarget();                                    //让敌人做第一次的漫游行走
    }
	    
	void FixedUpdate () {                                        //使用FixedUpdate函数定时监测状态的变换
        //Debug.Log("FixedUpdate()");
        UpdateFSM();
	}

    void UpdateFSM()                                             //主要使用switchcase函数来监测枚举变量currentState的变化来实现状态机的切换
    {
        //Debug.Log("UpdateFSM()");
        switch (currentState)
        {
            case FSMEnemyState.Wonder:
                UpdateWonderState();                             //如果是漫游状态则进入漫游状态的相关监测参数脚本
                break;
            case FSMEnemyState.Chase:
                UpdateChaseState();                              //如果是追逐状态则进入追逐状态的相关监测参数脚本
                break;
        }
    }

    void UpdateWonderState()                                     //在这个脚本里面我们监测在漫游状态下是否进行向其他状态的跳转
    {
        //Debug.Log("UpdateWonderState()");
        if (isachievetargetposition())                           //如果敌人到达漫游目的地，重新设定新漫游目的地，并让敌人前往那里
        {
            //Debug.Log("isachievewonderposition");
            setnewwondertarget();
        }
        if (isplayerinenemysight())                              //如果玩家出现在敌人视野中（玩家与敌人距离小于sightscope数值，前方定义，公开在unity中进行修改）则敌人状态跳转追逐状态
        {
            //Debug.Log("isplayerinenemysight");
            currentState = FSMEnemyState.Chase;                  //当前状态跳转
            setpositionforenemytochase();                        //将玩家所在地点设置成新漫游目的地让敌人前往
        }
    }

    void UpdateChaseState()                                      //进行追逐状态监测的函数
    {
        //Debug.Log("UpdateChaseState");
      //  if (isachievetargetposition())                           //如果到达追逐目的地，设定此时玩家位置为新追逐目的地，并让敌人前往
       // {
         //Debug.Log("isachievewonderposition");
            setpositionforenemytochase();
      //  }
        if (shoottimer > 2)                                     //每隔一秒射击玩家一次（很……傻……以后改改）
        {

            shootbulletatplayer();
            shoottimer = 0;
        }
        shoottimer += Time.deltaTime;
        if (isplayerinenemysight()==false)                              //如果玩家出现在敌人视野中（玩家与敌人距离小于sightscope数值，前方定义，公开在unity中进行修改）则敌人状态跳转追逐状态
        {
            //Debug.Log("isplayerinenemysight");
            currentState = FSMEnemyState.Wonder;                  //当前状态跳转
            
        }

    }

    void shootbulletatplayer()
    {
        GameObject go = GameObject.Instantiate(m_bullet);
       go.transform.position = enmfire_Position.position;
        go.transform.LookAt(m_playertransform);
        go.transform.forward+= new Vector3(Random.Range(-shellRange,shellRange), Random.Range(-shellRange, shellRange), Random.Range(-shellRange, shellRange));
        go.GetComponent<Rigidbody>().velocity = shellSpeed * go.transform.forward;

    }

    protected bool isachievetargetposition()                     //监测敌人是否到达漫游地点
    {
        return !m_Navagent.pathPending && m_Navagent.remainingDistance <= m_Navagent.stoppingDistance;//官方解读：是否到达漫游地点
    }

    protected bool isplayerinenemysight()                        //监测敌人是否进入玩家视野（玩家视野是一个以sightscope为半径的圆）
    {
        return Vector3.Distance(m_transform.position, m_playertransform.position)<sightscope;//玩家与敌人半径小于sightscope即为被发现（同样有些傻呀……后期改进吧）
    }

    void setnewwondertarget()                                    //设定漫游范围（一个以玩家为中心的边长是两倍wonderscope的正方体）中任意一点为新漫游地点
    {
        nextwonderposition = m_transform.position + new Vector3(Random.Range(-wonderscope, wonderscope), 0, Random.Range(-wonderscope, wonderscope));//将所计算的随机数加上原位置得到新位置
        m_Navagent.destination = nextwonderposition;
    }

    void setpositionforenemytochase()                            //设定玩家所在位置为新的追逐目的地   
    {
        m_Navagent.destination = m_playertransform.position;
    }
}
